package src.service;

import java.util.HashSet;
import java.util.Set;
import org.dozer.DozerBeanMapper;
import org.dozer.Mapper;
import src.data.IncomingMessageSRV;
import src.data.MailBoxSRV;
import src.data.OutgoingMessageSRV;
import src.domain.IncomingMessage;
import src.domain.MailBox;
import src.common.MessageStatus;
import src.domain.OutgoingMessage;
import src.domain.PostOffice;
import src.dto.LightMailBoxDTO;
import src.dto.MailBoxDTO;
import src.dto.OutgoingMessageDTO;


public class MailServerServiceDTO {

	private static MailServerServiceDTO instance = null;

	private MailServerServiceDTO() {
	}

	public static MailServerServiceDTO getInstance() {
		if (instance == null)
			instance = new MailServerServiceDTO();
		return instance;
	}
	
	/*private UserDTO createUserDTO(User user) {

		Mapper mapper = new DozerBeanMapper();
		UserDTO userDTO = mapper.map(user, UserDTO.class);
		
		return userDTO;


		/*UserDTO userDTO = new UserDTO();
		userDTO.setId(user.getId());
		userDTO.setVersion(user.getVersion());
		userDTO.setName(user.getName());
		userDTO.setUserName(user.getUserName());
		userDTO.setCity(user.getCity());
		userDTO.setAddress(user.getAddress());
		userDTO.setPhoneNumber(user.getPhoneNumber());
		userDTO.setActive(user.isActive());

		return userDTO;

	}*/

	private MailBoxDTO createMailBoxDTO(MailBox mailBox) {
		
		Mapper mapper = new DozerBeanMapper();
		MailBoxDTO mailBoxDTO = mapper.map(mailBox, MailBoxDTO.class);
		return mailBoxDTO;
	
	}

	private OutgoingMessageDTO createOutgoingMessageDTO(OutgoingMessage outgoingMessage) {
		Mapper mapper = new DozerBeanMapper();
		OutgoingMessageDTO outgoingMessageDTO = mapper.map(outgoingMessage, OutgoingMessageDTO.class);
		return outgoingMessageDTO;
	}
	
	/*private IncomingMessageDTO createIncomingMessageDTO(IncomingMessage incomingMessage){
		Mapper mapper = new DozerBeanMapper();
		IncomingMessageDTO incomingMessageDTO = mapper.map(incomingMessage, IncomingMessageDTO.class);
		return incomingMessageDTO;
		
		/*IncomingMessageDTO incomingMessageDTO=new IncomingMessageDTO();
		incomingMessageDTO.setId(incomingMessage.getId());
		incomingMessageDTO.setVersion(incomingMessage.getVersion());
		incomingMessageDTO.setOutgoingMessage(this.createOutgoingMessageDTO(incomingMessage.getOutgoingMessage()));
		incomingMessageDTO.setMessageStatus(incomingMessage.getMessageStatus());
		return incomingMessageDTO;*/
		
	//}
	
	private LightMailBoxDTO createLightMailBoxDTO(MailBox mailBox){
		Mapper mapper = new DozerBeanMapper();
		LightMailBoxDTO lightMailBoxDTO = mapper.map(mailBox, LightMailBoxDTO.class);
		return lightMailBoxDTO;
		
	}

	public MailBoxDTO signIn(final String nameMailBox, final String passMailBox) {
		return (MailBoxDTO) Executor.execute(new Closure() {
			public Object execute() {
				MailBox mailBox=MailBoxSRV.getByNameAndPass(nameMailBox, passMailBox);
				if(mailBox==null)
					return null;
				return createMailBoxDTO(mailBox);
			}
		});
	}

	public void sendMessage(final OutgoingMessageDTO outgoingMessageDTO) {
		Executor.execute(new Closure() {
			public Object execute() {
				OutgoingMessage outgoingMessage=new OutgoingMessage();
				outgoingMessage.setSubject(outgoingMessageDTO.getSubject());
				outgoingMessage.setContent(outgoingMessageDTO.getContent());
				outgoingMessage.setDate(outgoingMessageDTO.getDate());
				outgoingMessage.setTime(outgoingMessageDTO.getTime());
				outgoingMessage.setMessageClassification(outgoingMessageDTO.getMessageClassification());
				outgoingMessage.setSender(MailBoxSRV.getByID(outgoingMessageDTO.getSender().getId()));
				//Set<MailBox> targetMailBoxes=new HashSet<MailBox>();
				outgoingMessage.setTargetMailboxes(new HashSet<MailBox>());
				for(LightMailBoxDTO light: outgoingMessageDTO.getTargetMailboxes())
					outgoingMessage.getTargetMailboxes().add(MailBoxSRV.getByID(light.getId()));
				/*OutgoingMessage outgoingMessage=new OutgoingMessage(outgoingMessageDTO);
				OutgoingMessageSRV.save(outgoingMessage);
				for (MailBox mailBox : outgoingMessage.getSender().sendMessage(
						outgoingMessage))
					MailBoxSRV.update(mailBox);*/
				OutgoingMessageSRV.save(outgoingMessage);
				outgoingMessage.getSender().sendMessage(outgoingMessage);
				return null;
			}
		});
	}

	public void changeMessageStatus(final long idIncomingMessage,
			final MessageStatus messageStatus) {
		Executor.execute(new Closure() {
			public Object execute() {
				IncomingMessageSRV.getByID(idIncomingMessage).setMessageStatus(
						messageStatus);
				return null;
			}
		});

	}
	
	public void deleteIncomingMessage(final long idIncomingMessage) {
		Executor.execute(new Closure() {
			public Object execute() {
				IncomingMessage incomingMessage=new IncomingMessage();
				incomingMessage.setId(idIncomingMessage);
				
				//IncomingMessageSRV.delete(idIncomingMessage);
				MailBox m=IncomingMessageSRV.getMailBoxeByIncomingMessage(incomingMessage);
				if(m!=null)//no es necesario comprobar aca TODO: sacar esto
					m.getIncomingMessages().remove(incomingMessage);
				IncomingMessageSRV.delete(idIncomingMessage);
				return null;
			}
		});

	}
	
	@SuppressWarnings("unchecked")
	public Set<OutgoingMessageDTO> getOutgoingMessagesByMailBox(final long idMailBox) {
		return (Set<OutgoingMessageDTO>)Executor.execute(new Closure() {
			public Object execute() {
				Set<OutgoingMessageDTO> outgoingMessageDTOs=new HashSet<OutgoingMessageDTO>();
				for (OutgoingMessage o:OutgoingMessageSRV.getOutgoingMessages(idMailBox))
					outgoingMessageDTOs.add(createOutgoingMessageDTO(o));
				return outgoingMessageDTOs;
			}
		});

	}
	
	@SuppressWarnings("unchecked")
	public Set<LightMailBoxDTO>getContactsByMailBox(final long idMailBox){
		return (Set<LightMailBoxDTO>)Executor.execute(new Closure() {
			public Object execute() {
				
				MailBox mailBox=MailBoxSRV.getByID(idMailBox);
				Set<MailBox> mailBoxSet=new HashSet<MailBox>();
				
				for(PostOffice p:mailBox.getPostOffices()){
					mailBoxSet.addAll(MailBoxSRV.getMailBoxesByPostOffice(p));
					for(PostOffice post:p.getTrustOffices())
						mailBoxSet.addAll(MailBoxSRV.getMailBoxesByPostOffice(post));
				}
				
				Set<LightMailBoxDTO> lightMailBoxDTOs=new HashSet<LightMailBoxDTO>();
				
				for(MailBox m:mailBoxSet)
					lightMailBoxDTOs.add(createLightMailBoxDTO(m));
				
				return lightMailBoxDTOs;
			}
		});
	}
	
	public void deleteIncomingMessage1(final long idIncomingMessage) {
		Executor.execute(new Closure() {
			public Object execute() {
				IncomingMessage i=IncomingMessageSRV.getByID(idIncomingMessage);
				i.setOutgoingMessage(null);
				IncomingMessageSRV.delete(idIncomingMessage);
				
			
				return null;
			}
		});

	}
	
	public boolean changePassword(final long idMailBox,final String oldPass,final String newPass){
		return (Boolean) Executor.execute(new Closure() {
			public Object execute() {
				MailBox mailBox=MailBoxSRV.getByID(idMailBox);
				if(mailBox.getPass().equals(oldPass)){
					mailBox.setPass(newPass);
					return true;
				}
				return false;
			}
		});
	}
}
